package com.example.exceldemo.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.exceldemo.dao.ParsedExcelDataDao;
import com.example.exceldemo.exception.BizException;
import com.example.exceldemo.listener.ReqDataListener;
import com.example.exceldemo.model.ParsedExcelData;
import com.example.exceldemo.model.ParsedExcelDataEntity;
import com.example.exceldemo.model.ReqInfoDTO;
import com.example.exceldemo.service.ParsedExcelDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * Excel解析数据缓存服务实现类
 */
@Slf4j
@Service
public class ParsedExcelDataServiceImpl extends ServiceImpl<ParsedExcelDataDao, ParsedExcelDataEntity> implements ParsedExcelDataService {

    @Override
    public ParsedExcelData saveExcelData(String filePath, String dataJson, int expireDays) {
        return null;
    }

    @Override
    public ParsedExcelData saveExcelDataWithHash(String fileHash, String originalFilename, String dataJson, int expireDays) {
        return null;
    }

    @Override
    public Optional<String> getExcelDataByFile(File file) {
        return Optional.empty();
    }

    @Override
    public Optional<String> getExcelDataByPath(String filePath) {
        return Optional.empty();
    }

    @Override
    public Optional<String> getExcelDataByOriginalFilename(String originalFilename) {
        return Optional.empty();
    }

    @Override
    public boolean updateLastAccessTime(Long id, LocalDateTime lastAccessTime) {
        return false;
    }

    @Override
    public int cleanExpiredData() {
        return 0;
    }

    @Override
    public String getFileHash(File file) {
        return "";
    }

    @Override
    public String getFileHash(byte[] bytes) {
        return "";
    }

    @Override
    public ParsedExcelResult saveExcelData(MultipartFile file) {
        try {
            // 计算文件哈希值
            String fileHash = calculateFileHash(file);
            log.info("计算上传文件哈希值: {}", fileHash);
            
            // 检查缓存中是否存在
            if (isExcelDataCached(fileHash)) {
                log.info("文件已缓存，直接返回缓存数据: {}", fileHash);
                List<ReqInfoDTO> reqInfoList = getExcelDataByHash(fileHash);
                // 更新最后访问时间
                baseMapper.updateLastAccessTime(fileHash);
                return new ParsedExcelResult(fileHash, reqInfoList);
            }
            
            // 解析Excel文件
            log.info("开始解析Excel文件: {}", file.getOriginalFilename());
            byte[] fileBytes = file.getBytes();
            ReqDataListener listener = new ReqDataListener();
            List<ReqInfoDTO> reqInfoList = EasyExcel.read(new ByteArrayInputStream(fileBytes))
                    .head(ReqInfoDTO.class)
                    .registerReadListener(listener)
                    .sheet()
                    .doReadSync();
            
            if (CollectionUtils.isEmpty(reqInfoList)) {
                log.warn("Excel文件中未找到有效的需求数据");
                throw BizException.fileParseError("Excel文件中未找到有效的需求数据");
            }
            
            log.info("Excel处理完成，共读取{}条记录", reqInfoList.size());
            
            // 将数据转换为JSON存储
            String dataJson = JSON.toJSONString(reqInfoList);
            
            // 保存到数据库
            ParsedExcelDataEntity entity = new ParsedExcelDataEntity();
            entity.setFileHash(fileHash);
            entity.setFileName(file.getOriginalFilename());
            entity.setDataJson(dataJson);
            entity.setReqCount(reqInfoList.size());
            entity.setUploadTime(LocalDateTime.now());
            entity.setLastAccessTime(LocalDateTime.now());
            
            save(entity);
            log.info("Excel解析数据已保存到数据库, hash: {}", fileHash);
            
            return new ParsedExcelResult(fileHash, reqInfoList);
        } catch (Exception e) {
            log.error("解析Excel文件失败", e);
            throw BizException.fileParseError("解析Excel文件失败: " + e.getMessage());
        }
    }

    @Override
    public List<ReqInfoDTO> getExcelDataByHash(String fileHash) {
        ParsedExcelDataEntity entity = baseMapper.findByFileHash(fileHash);
        if (entity == null) {
            log.warn("未找到对应哈希值的缓存数据: {}", fileHash);
            return null;
        }
        
        try {
            // 更新最后访问时间
            baseMapper.updateLastAccessTime(fileHash);
            
            // 将JSON转换为对象
            return JSON.parseArray(entity.getDataJson(), ReqInfoDTO.class);
        } catch (Exception e) {
            log.error("解析缓存数据失败", e);
            throw BizException.fileParseError("解析缓存数据失败: " + e.getMessage());
        }
    }

    @Override
    public boolean isExcelDataCached(String fileHash) {
        return baseMapper.findByFileHash(fileHash) != null;
    }

    @Override
    public String calculateFileHash(MultipartFile file) {
        try {
            byte[] bytes = file.getBytes();
            return DigestUtils.md5DigestAsHex(bytes);
        } catch (IOException e) {
            log.error("计算文件哈希值失败", e);
            throw BizException.fileParseError("计算文件哈希值失败: " + e.getMessage());
        }
    }
} 